/**
 * MIT License
 * Copyright (c) 2018 yadong.zhang
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.xuyiwei.xblog.modular.controller;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.xuyiwei.xblog.business.article.model.Tags;
import com.xuyiwei.xblog.business.article.result.article.input.ArticleConditionVO;
import com.xuyiwei.xblog.business.article.result.article.input.CommentConditionVO;
import com.xuyiwei.xblog.business.article.result.article.out.ArticleDto;
import com.xuyiwei.xblog.business.article.result.article.out.CommentDto;
import com.xuyiwei.xblog.business.article.service.IArticleService;
import com.xuyiwei.xblog.business.article.service.ICommentService;
import com.xuyiwei.xblog.business.article.service.ITagsService;
import com.xuyiwei.xblog.business.article.service.ITypeService;
import com.xuyiwei.xblog.business.system.model.User;
import com.xuyiwei.xblog.business.system.result.user.input.UserLogin;
import com.xuyiwei.xblog.business.system.result.user.input.UserRegister;
import com.xuyiwei.xblog.business.system.service.IConfigService;
import com.xuyiwei.xblog.business.system.service.ILinkService;
import com.xuyiwei.xblog.business.system.service.IUserService;
import com.xuyiwei.xblog.core.base.constant.enums.ArticleStatusEnum;
import com.xuyiwei.xblog.core.base.constant.enums.CommonStatusEnum;
import com.xuyiwei.xblog.core.base.controller.BaseController;
import com.xuyiwei.xblog.core.base.response.Result;
import com.xuyiwei.xblog.core.common.constant.factory.PageFactory;
import com.xuyiwei.xblog.core.exception.GunsException;
import com.xuyiwei.xblog.core.log.LogManager;
import com.xuyiwei.xblog.core.log.factory.LogTaskFactory;
import com.xuyiwei.xblog.core.shiro.ShiroKit;
import com.xuyiwei.xblog.core.shiro.ShiroUser;
import com.xuyiwei.xblog.core.util.RSAUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;

import static com.xuyiwei.xblog.core.support.HttpKit.getIp;

/**
 * 页面跳转类
 *
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0
 * @website https://www.zhyd.me
 * @date 2018/4/18 11:48
 * @since 1.0
 */
@Controller
public class RenderController extends BaseController {
    /**
     * sidebar部分的推荐、近期和随机tab页中显示的文章数
     */
    private static final int SIDEBAR_ARTICLE_SIZE = 8;
    private static final String PREFIX = "/index";

    private static final String NOT_ONLINE_HTML = "/not_online.html";

    @Autowired
    private ILinkService linkService;

    @Autowired
    private IArticleService articleService;

    @Autowired
    private ITypeService typeService;

    @Autowired
    private ITagsService tagsService;

    @Autowired
    private ICommentService commentService;

    @Autowired
    private IConfigService configService;

    @Autowired
    private IUserService userService;

    /**
     * 加载首页的数据
     *
     * @param vo
     * @param model
     * @return
     */
    private void loadIndexPage(ArticleConditionVO vo, Model model) {
        model.addAttribute("model", vo);

        Page<ArticleDto> articlePage;
        if(vo.getPageNumber()==null){
            articlePage = new PageFactory<ArticleDto>().defaultPage();

        }else{
            articlePage = new PageFactory<ArticleDto>().defaultPage(10,(vo.getPageNumber()-1)*10);
        }
        vo.setStatus(CommonStatusEnum.USE.getKey());
        List<ArticleDto> articles = articleService.findPageByCondition(articlePage,vo,articlePage.getOrderByField(),articlePage.isAsc());
        model.addAttribute("page", super.packForBT(articlePage.setRecords(articles)));
        model.addAttribute("links", linkService.listOfIndex());
        model.addAttribute("types", typeService.listTypeForMenu());
        EntityWrapper<Tags> tagsWrapper = new EntityWrapper<>();
        tagsWrapper.eq("status",CommonStatusEnum.USE.getKey());
        model.addAttribute("tags", tagsService.selectList(tagsWrapper));


        Page<CommentDto> commentPage = new PageFactory<CommentDto>().defaultPage();
        commentPage.setSize(10);
        List<CommentDto> recentCommnets = commentService.findPageByCondition(commentPage,new CommentConditionVO(),commentPage.getOrderByField(),commentPage.isAsc());
        model.addAttribute("recentCommnets", recentCommnets);

        Map<String,Object> siteInfo = configService.getSiteInfo();
        model.addAttribute("siteInfo", siteInfo);

        List<ArticleDto> recentArtcles = articleService.listRecent(10);
        model.addAttribute("recentArtcles", recentArtcles);

        List<ArticleDto> recommendeds = articleService.listRecommended(10);
        model.addAttribute("recommendeds", recommendeds);

        List<ArticleDto> randoms = articleService.listRandom(10);
        model.addAttribute("randoms", randoms);


        model.addAttribute("onlineNum", randoms);

     }



    /**
     * 首页
     * 默认0页 每页10条
     * @param model
     * @return
     */
    @RequestMapping("/")
    public String home( Model model,ArticleConditionVO vo) {
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return "/index.html";
    }

    /**
     * 首页
     * 根据传递过来的页码数传递
     * @param vo
     * @return
     */
    @RequestMapping("/index/{pageNumber}")
    public String home(@PathVariable("pageNumber") Integer pageNumber,ArticleConditionVO vo , Model model) {
        vo.setPageNumber(pageNumber);
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return  "/index.html";
    }

    /**
     * 首页
     * 根据传递过来的页码数传递
     * @param model
     * @return
     */
    @RequestMapping("/type/{typeId}")
    public String type(@PathVariable("typeId") Long typeId, Model model) {
        ArticleConditionVO vo = new ArticleConditionVO();
        vo.setTypeId(typeId);
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return  "/index.html";
    }

    /**
     * 首页
     * 根据传递过来的页码数传递
     * @param model
     * @return
     */
    @RequestMapping("/type/{typeId}/{pageNumber}")
    public String type(@PathVariable("typeId") Long typeId, @PathVariable("pageNumber") Integer pageNumber,
                       Model model) {
        ArticleConditionVO vo = new ArticleConditionVO();
        vo.setTypeId(typeId);
        vo.setPageNumber(pageNumber);
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return  "/index.html";
    }

    /**
     * 首页
     * 根据传递过来的页码数传递
     * @param model
     * @return
     */
    @RequestMapping("/tag/{tagId}")
    public String tag(@PathVariable("tagId") Long tagId, Model model) {
        ArticleConditionVO vo = new ArticleConditionVO();
        vo.setTagId(tagId);
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return  "/index.html";
    }

    /**
     * 首页
     * 根据传递过来的页码数传递
     * @param model
     * @return
     */
    @RequestMapping("/tag/{tagId}/{pageNumber}")
    public String tag(@PathVariable("tagId") Long tagId, @PathVariable("pageNumber") Integer pageNumber,
                       Model model) {
        ArticleConditionVO vo = new ArticleConditionVO();
        vo.setTagId(tagId);
        vo.setPageNumber(pageNumber);
        loadIndexPage(vo, model);
        model.addAttribute("url", PREFIX);
        return  "/index.html";
    }

    /**
     * 文章详情
     *
     * @param model
     * @param articleId
     * @return
     */
    @GetMapping("/article/{articleId}")
    public String article(Model model, @PathVariable("articleId") Long articleId) {
        ArticleConditionVO vo = new ArticleConditionVO();
        vo.setArticleId(articleId);
        List<ArticleDto> articles = articleService.findPageByCondition(new PageFactory<ArticleDto>().defaultPage(),
                vo,null,true);

        if (articles == null || articles.size()==0 || ArticleStatusEnum.UNPUBLISHED.getKey() == articles.get(0).getStatus()) {
            return "/error/404.html";
        }
        model.addAttribute("article", articles.get(0));
        // 上一篇下一篇
        model.addAttribute("other", articleService.getPrevAndNextArticles(articles.get(0).getCreateTime()));
        // 相关文章
        model.addAttribute("relatedList", articleService.listRelatedArticle(SIDEBAR_ARTICLE_SIZE, articles.get(0)));

        // 相关文章
        model.addAttribute("hostList", articleService.listHotArticle(10));
        EntityWrapper<Tags> tagsWrapper = new EntityWrapper<>();
        tagsWrapper.eq("status",CommonStatusEnum.USE.getKey());
        model.addAttribute("tags", tagsService.selectList(tagsWrapper));
        model.addAttribute("types", typeService.listTypeForMenu());
        model.addAttribute("articleDetail", true);
        return "/article.html";
    }

    /**
     * 关于页面
     * @return
     */
    @GetMapping("about")
    public String about(Model model){
        model.addAttribute("types", typeService.listTypeForMenu());
        return "/about.html";
    }

    /**
     * 留言板
     * @param model
     * @return
     */
    @GetMapping("guestbook")
    public String guestbook(Model model){
        model.addAttribute("types", typeService.listTypeForMenu());
        return NOT_ONLINE_HTML;
    }

    /**
     * 友情链接
     * @param model
     * @return
     */
    @GetMapping("links")
    public String links(Model model){
        model.addAttribute("types", typeService.listTypeForMenu());
        return NOT_ONLINE_HTML;
    }

    /**
     * 登录
     * @param model
     * @return
     */
    @GetMapping("login")
    public String login(Model model){
        return "/login.html";
    }

    /**
     * 跳转注册用户页面
     * @param model
     * @return
     */
    @GetMapping("register")
    public String register(Model model){
        return "/register.html";
    }

    /**
     * 注册用户方法
     * @param userRegister
     * @return
     */
    @PostMapping("registerAction")
    public  String registerUser(Model model, @Valid UserRegister userRegister, BindingResult bindingResult) throws MalformedURLException {
        if (bindingResult.hasErrors()) {
            model.addAttribute("tips","注册信息请填写完整");
            return "/register.html";
        }else{
            userService.registerUser(userRegister);
            return "/login.html";
        }
    }

    /**
     * 注册用户方法
     * @param userLogin
     * @return
     */
    @PostMapping("loginAction")
    public  String loginAction(Model model, @Valid UserLogin userLogin, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            model.addAttribute("tips","注册信息请填写完整");
            return "/login.html";
        }else{
            String account = userLogin.getAccount();
            String password = userLogin.getPassword();
            // 完善账号信息
            account = RSAUtil.decryptBase64(account);
            password = RSAUtil.decryptBase64(password);
            Subject currentUser = ShiroKit.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(account, password.toCharArray());

            if ("on".equals(userLogin.getRemember())) {
                token.setRememberMe(true);
            } else {
                token.setRememberMe(false);
            }

            currentUser.login(token);

            //如果这里还没有抛出异常则表示登录成功  因此登录次数+1
            userService.addLongCount(account);

            ShiroUser shiroUser = ShiroKit.getUser();
            super.getSession().setAttribute("shiroUser", shiroUser);
            super.getSession().setAttribute("username", shiroUser.getAccount());

            LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));

            ShiroKit.getSession().setAttribute("sessionFlag", true);

            return REDIRECT + "/";
        }
    }

    /**
     * 注册用户方法
     * @return
     */
    @GetMapping("loginOut")
    public  String loginOut(Model model) {
        Subject currentUser = SecurityUtils.getSubject();
        currentUser.logout();
        return REDIRECT + "/";
    }
}
